package cn.lg.soar.activiti.service.impl;

import cn.lg.soar.activiti.api.model.*;
import cn.lg.soar.activiti.mapper.ActivitiMapper;
import cn.lg.soar.activiti.service.ActivitiService;
import cn.lg.soar.common.util.current.UserContext;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceBuilder;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class ActivitiServiceImpl implements ActivitiService {

	private final Logger log = LoggerFactory.getLogger(ActivitiServiceImpl.class);

	private final ActivitiMapper activitiMapper;
	private final RuntimeService runtimeService;
	private final TaskService taskService;

	public ActivitiServiceImpl(ActivitiMapper activitiMapper, RuntimeService runtimeService, TaskService taskService) {
		this.activitiMapper = activitiMapper;
		this.runtimeService = runtimeService;
		this.taskService = taskService;
	}

	@Transactional(rollbackFor = RuntimeException.class)
	@Override
	public ProcessInstanceDTO startProcess(StartProcessDTO dto) {
		String key = dto.getProcessKey();
		String businessKey = dto.getBusinessId();
		String title = dto.getTitle();
		Map<String, Object> variables = dto.getVariables();
		CompleteTaskDTO completeTask = dto.getCompleteTask();
		String tenantId = String.valueOf(UserContext.getUser().getCurrentTenantId());
		// 启动流程
		ProcessInstanceBuilder builder = runtimeService.createProcessInstanceBuilder()
				.processDefinitionKey(key)
				.businessKey(businessKey)
				.tenantId(tenantId);
		if (StringUtils.hasText(title)) {
			builder.processInstanceName(title);
		}
		ProcessInstance pi = builder.start();
		runtimeService.setVariables(pi.getId(), variables);
		// 自动完成第一个任务节点
		if (completeTask != null) {
			Task task = taskService.createTaskQuery()
					.processInstanceId(pi.getProcessInstanceId())
					.active()
					.singleResult();
			completeTask.setTaskId(task.getId());
			completeTask(completeTask);
		}
//		ProcessInstance pi = runtimeService.startProcessInstanceByKeyAndTenantId(key, businessKey, variables, tenantId);
		// 返回数据
		ProcessInstanceDTO processInstanceDTO = new ProcessInstanceDTO();
		processInstanceDTO.setProcessDefinitionId(pi.getProcessDefinitionId());
		processInstanceDTO.setProcessVariables(pi.getProcessVariables());
		processInstanceDTO.setBusinessKey(pi.getBusinessKey());
		processInstanceDTO.setDescription(pi.getDescription());
		processInstanceDTO.setDeploymentId(pi.getDeploymentId());
		processInstanceDTO.setProcessDefinitionKey(pi.getProcessDefinitionKey());
		processInstanceDTO.setProcessDefinitionName(pi.getProcessDefinitionName());
		processInstanceDTO.setProcessDefinitionVersion(pi.getProcessDefinitionVersion());
		processInstanceDTO.setLocalizedDescription(pi.getLocalizedDescription());
		processInstanceDTO.setLocalizedName(pi.getLocalizedName());
		log.info("启动流程成功：{}", dto);
		return processInstanceDTO;
	}

	@Transactional(rollbackFor = RuntimeException.class)
	@Override
	public void completeTask(CompleteTaskDTO dto) {
		String taskId = dto.getTaskId();
		String comment = dto.getComment();
		List<String> candidates = dto.getCandidates();
		Map<String, List<String>> taskCandidates = dto.getTaskCandidates();
		// 查询当前任务
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		Assert.notNull(task, "任务不存在");
		// 节点任务处理人
		taskService.setAssignee(taskId, UserContext.getUser().getUsername());
		if (StringUtils.hasText(comment)) {
			// 添加评论
			taskService.addComment(taskId, null, dto.getComment());
		}
		// 完成节点任务
		taskService.complete(taskId, dto.getVariables());
		// 设置下个节点候选人（单个节点）
		if (!CollectionUtils.isEmpty(candidates)) {
			// 当前活动的任务
			task = taskService.createTaskQuery()
					.processInstanceId(task.getProcessInstanceId())
					.active()
					.singleResult();
			taskId = task.getId();
			Set<String> set = new HashSet<>(candidates);
			for (String s : set) {
				taskService.addCandidateUser(taskId, s);
			}
		}
		// 设置下个节点候选人（多个节点）
		if (!CollectionUtils.isEmpty(taskCandidates)) {
			List<Task> tasks = taskService.createTaskQuery()
					.processInstanceId(task.getProcessInstanceId())
					.active()
					.list();
			for (Task t : tasks) {
				candidates = taskCandidates.get(t.getTaskDefinitionKey());
				Set<String> set = new HashSet<>(candidates);
				taskId = t.getId();
				for (String s : set) {
					taskService.addCandidateUser(taskId, s);
				}
			}
		}
		log.info("完成任务成功：{}", dto);
	}

	@Override
	public List<TaskDTO> tasks(String processKey, Collection<String> businessIds, Collection<String> candidates) {
		String tenantId = String.valueOf(UserContext.getUser().getCurrentTenantId());
		return activitiMapper.tasks(tenantId, processKey, new HashSet<>(businessIds), new HashSet<>(candidates));
	}

	@Override
	public List<HistoryTaskDTO> historyTasks(String processKey, String businessId) {
		String tenantId = String.valueOf(UserContext.getUser().getCurrentTenantId());
		return activitiMapper.historyTasks(tenantId, processKey, businessId);
	}

}
